package com.rankeiot.core.inner;

import com.rankeiot.core.data.KvMap;
import com.rankeiot.core.inner.argumet.QueryPage;
import com.rankeiot.core.util.JSONUtil;
import com.rankeiot.core.util.StringUtil;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.core.MethodParameter;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;


import java.util.HashMap;
import java.util.Map;

import static com.rankeiot.core.inner.QueryParamsMethodArgumentResolver.filterNames;

public class PageQueryMethodArgumentResolver implements HandlerMethodArgumentResolver {
    private final String PAGE_NO = "pageNo";
    private final String PAGE_SIZE = "pageSize";
    private final String SORT = "sort";
    private final String SKIP_QUERY_COUNT = "skipQueryCount";
    public static int pageSizeLimit = 1000;

    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        return parameter.getParameterType().equals(QueryPage.class);
    }

    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
        QueryPage pageQuery = new QueryPage();
        HashMap query = new HashMap();

        HttpServletRequest servletRequest = webRequest.getNativeRequest(HttpServletRequest.class);
        ServletServerHttpRequest inputMessage = new ServletServerHttpRequest(servletRequest);

        if (inputMessage.getMethod() == HttpMethod.GET || inputMessage.getMethod() == HttpMethod.DELETE) {
            Map<String, String[]> parameterMap = webRequest.getParameterMap();
            parameterMap.forEach((key, values) -> {
                if (values.length > 0) {
                    query.put(key, values[0]);
                }
            });
        } else if (inputMessage.getHeaders().getContentType().equalsTypeAndSubtype(MediaType.APPLICATION_JSON)) {
            String body = StringUtil.read(inputMessage.getBody());
            if (StringUtil.isEmpty(body)) {
                return pageQuery;
            }
            query.putAll(JSONUtil.parseObject(body));
        } else {
            Map<String, String[]> parameterMap = webRequest.getParameterMap();
            parameterMap.forEach((key, values) -> {
                if (values.length > 0) {
                    query.put(key, values[0]);
                }
            });
        }

        pageQuery.setParams(query);
        if (query.containsKey(PAGE_NO)) {
            pageQuery.setPageNo(pageQuery.getLong(PAGE_NO));
            query.remove(PAGE_NO);
        }
        if (query.containsKey(PAGE_SIZE)) {
            int pageSize = Math.min(pageSizeLimit, pageQuery.getInteger(PAGE_SIZE));
            pageQuery.setPageSize(pageSize);
            query.remove(PAGE_SIZE);
        }
        if (query.containsKey(SKIP_QUERY_COUNT)) {
            boolean skipQueryCount = pageQuery.getBoolean(SKIP_QUERY_COUNT);
            pageQuery.setSkipQueryCount(skipQueryCount);
            query.remove(SKIP_QUERY_COUNT);
        }
        if (query.containsKey(SORT)) {
            String sort = pageQuery.getStr(SORT);
            if (StringUtil.isNotEmpty(sort)) {
                QueryParamsMethodArgumentResolver.validateSort(sort);
            }
        }
        filterNames(query);
        return pageQuery;
    }
}
